﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RaytracerLib.Materials;
using YAXLib;
using System.Diagnostics;
using System.Collections;

namespace RaytracerLib.RenderableObjects
{
    public class RenderableObjectMaterials : IEnumerable<Material>
    {
        private List<Material> m_materials;
        private List<string> m_names;
        private Scene m_scene;

        public Scene Scene
        {
            get
            {
                return m_scene;
            }
            set
            {
                if (value == null)
                {
                    if (m_materials != null)
                        m_materials = m_materials.Select(m => m.DeepClone()).ToList();
                }
                else
                {
                    if (m_materials != null)
                    {
                        for (int i = 0; i < m_materials.Count; i++)
                            m_materials[i] = value.Materials.AddOrFind(m_materials[i]);
                    }
                    else if (m_names != null)
                    {
                        m_materials = m_names.Select(m => value.Materials[m]).ToList();

                        if (m_materials.Any(m => m == null))
                            throw new InvalidOperationException();

                        m_names = null;
                    }
                }

                m_scene = value;
            }
        }

        [YAXCollection("Materials", ElementName = "Material", 
            SerializationType = YAXCollectionSerializationTypes.InnerCollectionRecursiveInElement)]
        private List<string> Names
        {
            get
            {
                if (m_materials != null)
                    return m_materials.Select(m => m.Name).ToList();
                else
                    return m_names;
            }
            set
            {
                m_names = value;
            }
        }

        public Material this[int a_index]
        {
            get
            {
                if (m_materials.Count <= a_index)
                    return null;
                else
                    return m_materials[a_index];
            }
            set
            {
                if (Scene != null)
                    value = Scene.Materials.AddOrFind(value);

                if (m_materials == null)
                    m_materials = new List<Material>();

                while (m_materials.Count <= a_index)
                    m_materials.Add(null);

                m_materials[a_index] = value;
            }
        }

        public IEnumerator<Material> GetEnumerator()
        {
            return m_materials.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return m_materials.GetEnumerator();
        }
    }
}
